package com.ljf.common.domain.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ljf.common.domain.repository.IBasisRepository;
import com.ljf.common.dto.query.PageParam;
import com.ljf.common.exception.ServiceException;
import com.ljf.common.model.BasisModel;
import com.ljf.common.utils.BeanConversionUtil;
import org.springframework.context.ApplicationContext;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

/**
 * 基础领域服务
 *
 * @author LJF
 * @since 2024-01-26
 */
public class BasisDomainService<R extends IBasisRepository<Q, V, M>, Q extends PageParam, V extends Serializable, M extends BasisModel, A extends Serializable> extends NoDBBasisDomainService {

    @Resource
    private ApplicationContext applicationContext;

    protected R repository;

    private Class<R> repositoryClass;

    /**
     * 分页查询
     *
     * @param query
     * @return
     * @throws ServiceException
     */
    public Page<V> query(Q query) throws ServiceException {
        return repository.selectPageList(query);
    }

    /**
     * 查询
     *
     * @param query
     * @return
     * @throws ServiceException
     */
    public List<V> queryList(Q query) throws ServiceException {
        return repository.selectList(query);
    }

    /**
     * 根据ID更新
     *
     * @param command
     * @return
     * @throws ServiceException
     */
    public Boolean edit(A command) throws ServiceException {
        M updateModel = BeanConversionUtil.conversionObj(command, (Class<M>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[3]);
        return repository.updateById(updateModel) > 0;
    }

    /**
     * 根据ID查询
     *
     * @param id
     * @return
     * @throws ServiceException
     */
    public V queryById(Long id) throws ServiceException {
        V v = repository.selectById(id);
        if (v == null) {
            throw new ServiceException("通用ID查询异常:数据不存在");
        }
        return v;
    }

    /**
     * 查询接口(仅一条数据)
     *
     * @param query
     * @param noRecordMsg
     * @param multipleRecordMsg
     * @return
     * @throws ServiceException
     */
    public V queryOne(Q query, String noRecordMsg, String multipleRecordMsg) throws ServiceException {
        int count = repository.count(query);
        if (count == 0) {
            throw new ServiceException(noRecordMsg);
        } else if (count > 1) {
            throw new ServiceException(multipleRecordMsg);
        }
        query.setCurrent(1);
        query.setSize(1);
        Page<V> vPage = repository.selectPageList(query);
        return vPage.getRecords().get(0);
    }

    /**
     * 查询接口(仅一条数据)
     *
     * @param query
     * @return
     * @throws ServiceException
     */
    public V queryOne(Q query) throws ServiceException {
        return queryOne(query, "通用唯一查询异常:记录不存在", "通用唯一查询异常:存在多条记录");
    }

    /**
     * 新增
     *
     * @param command
     * @return
     * @throws ServiceException
     */
    public M add(A command) throws ServiceException {
        M insertModel = BeanConversionUtil.conversionObj(command, (Class<M>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[3]);
        return repository.insert(insertModel);
    }

    /**
     * 删除
     *
     * @param id
     * @return
     * @throws ServiceException
     */
    public boolean delete(Long id) throws ServiceException {
        return repository.deleteById(id) > 0;
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     * @throws ServiceException
     */
    public boolean deleteBatch(List<Long> ids) throws ServiceException {
        if (repository.countByIds(ids) <= 0) {
            throw new ServiceException("通用删除异常:无数据可删除");
        }
        return repository.deleteBatchByIds(ids) > 0;
    }

    @PostConstruct
    public void init() {
        this.getRepository();
    }

    /**
     * 获取数据访问对象
     *
     * @return
     */
    private R getRepository() {
        if (this.repository == null) {
            Class<R> sampleObjectCallBack = this.getSuperClassGenricType(0);
            this.repository = this.applicationContext.getBean(sampleObjectCallBack);
        }
        return this.repository;
    }

    /**
     * 获取服务Bean类型
     *
     * @param index
     * @return
     */
    private Class<R> getSuperClassGenricType(int index) {
        ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
        int count = type.getActualTypeArguments().length;
        if (count > 0) {
            this.repositoryClass = (Class) type.getActualTypeArguments()[index];
        }
        return this.repositoryClass;
    }

}
